<?php
/**
 * @package Joostina
 * @copyright Авторские права (C) 2008-2010 Joostina team. Все права защищены.
 * @license Лицензия http://www.gnu.org/licenses/gpl-2.0.htm GNU/GPL, или help/license.php
 * Joostina! - свободное программное обеспечение распространяемое по условиям лицензии GNU/GPL
 * Для получения информации о используемых расширениях и замечаний об авторском праве, смотрите файл help/copyright.php.
 */
// запрет прямого доступа
defined('_VALID_MOS') or die();
/**
 *  PHP Client Sniffer (phpsniff)
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *  
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *  
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  @author Roger Raymond <epsilon7@users.sourceforge.net>
 *  @version $Id: phpSniff.class.php,v 1.22 2004/04/27 00:55:49 epsilon7 Exp $
 *  @copyright Copyright &copy; 2002-2004 Roger Raymond
 *  @package phpSniff
 *  @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License
 *  @filesource
 */
/**
 *  PHP Sniffer Class
 *
 *  Used to determine the browser and other associated properies
 *  using nothing other than the HTTP_USER_AGENT value supplied by a
 *  user's web browser.
 *
 *  @package phpSniff
 *  @access public
 *  @author Roger Raymond <epsilon7@users.sourceforge.net>
 */
class phpSniff {
	/**
	 * @access private
	 * @var string
	 */
	var $_version = '2.1.4';
	/**
	 *  $_temp_file_path
	 *      default : /tmp/
	 *      desc    : directory writable by the server to store cookie check files.
	 *              : trailing slash is needed. only used if you use the check cookie routine
	 *
	 *  @access public
	 *  @var string
	 */
	var $_temp_file_path = '/cache/'; // with trailing slash
	/**
	 *  $_check_cookies
	 *      default : null
	 *      desc    : Allow for the script to redirect the browser in order
	 *              : to check for cookies.   In order for this to work, this
	 *              : class must be instantiated before any headers are sent.
	 *
	 *  @access public
	 *  @var string
	 */
	var $_check_cookies = null;
	/**
	 *  $_default_language
	 *      default : en-us
	 *      desc    : language to report as if no languages are found
	 *  @access public
	 *  @var string
	 */
	var $_default_language = 'ru-ru';
	/**
	 *  default : null
	 *  Allow for browser to Masquerade as another. (ie: Opera identifies as MSIE 5.0)
	 *
	 *  @access public
	 *  @var string
	 */
	var $_allow_masquerading = null;
	/**
	 *  @access private
	 *  @var string
	 */
	var $_php_version = '';
	/**
	 *  2D Array of browsers we wish to search for in key => value pairs.
	 *  <pre>
	 *  key   = browser to search for [as in HTTP_USER_AGENT]
	 *  value = value to return as 'browser' property
	 *  </pre>
	 *
	 *  @access public
	 *  @var array
	 */
	var $_browsers = array('microsoft internet explorer' => 'IE','msie' => 'IE',
		'netscape6' => 'NS','netscape' => 'NS','galeon' => 'GA','phoenix' => 'PX',
		'mozilla firebird' => 'FB','firebird' => 'FB','firefox' => 'FX','chimera' =>
		'CH','camino' => 'CA','epiphany' => 'EP','safari' => 'SF','k-meleon' => 'KM',
		'mozilla' => 'MZ','opera' => 'OP','konqueror' => 'KQ','icab' => 'IC','lynx' =>
		'LX','links' => 'LI','ncsa mosaic' => 'MO','amaya' => 'AM','omniweb' => 'OW',
		'hotjava' => 'HJ','browsex' => 'BX','amigavoyager' => 'AV','amiga-aweb' => 'AW',
		'ibrowse' => 'IB');
	/**
	 *  $_javascript_versions
	 *      desc    : 2D Array of javascript version supported by which browser
	 *              : in key => value pairs.
	 *              : key   = javascript version
	 *              : value = search parameter for browsers that support the
	 *              :         javascript version listed in the key (comma delimited)
	 *              :         note: the search parameters rely on the values
	 *              :               set in the $_browsers array
	 *  @access public
	 *  @var array
	 */
	var $_javascript_versions = array('1.5' =>
		'NS5+,MZ,PX,FB,FX,GA,CH,CA,SF,KQ3+,KM,EP',
		// browsers that support JavaScript 1.5
		'1.4' => '','1.3' => 'NS4.05+,OP5+,IE5+','1.2' => 'NS4+,IE4+','1.1' =>
		'NS3+,OP,KQ','1.0' => 'NS2+,IE3+','0' => 'LI,LX,HJ');
	/**
	 *  $_browser_features
	 *      desc    : 2D Array of browser features supported by which browser
	 *              : in key => value pairs.
	 *              : key   = feature
	 *              : value = search parameter for browsers that support the
	 *              :         feature listed in the key (comma delimited)
	 *              :         note: the search parameters rely on the values
	 *              :               set in the $_browsers array
	 *  @access public
	 *  @var string
	 */
	var $_browser_features = array( /**
		 *    the following are true by default
		 *    (see phpSniff.core.php $_feature_set array)
		 *    browsers listed here will be set to false
		 **/'html' => '','images' => 'LI,LX','frames' => 'LX','tables' => '','java' =>
		'OP3,LI,LX,NS1,MO,IE1,IE2','plugins' => 'IE1,IE2,LI,LX', /**
		 *    the following are false by default
		 *    (see phpSniff.core.php $_feature_set array)
		 *    browsers listed here will be set to true
		 **/'css2' => 'NS5+,IE5+,MZ,PX,FB,FX,CH,CA,SF,GA,KQ3+,OP7+,KM,EP','css1' =>
		'NS4+,IE4+,MZ,PX,FB,FX,CH,CA,SF,GA,KQ,OP7+,KM,EP','iframes' =>
		'LI,IE3+,NS5+,MZ,PX,FB,FX,CH,CA,SF,GA,KQ,OP7+,KM,EP','xml' =>
		'IE5+,NS5+,MZ,PX,FB,FX,CH,CA,SF,GA,KQ,OP7+,KM,EP','dom' =>
		'IE5+,NS5+,MZ,PX,FB,FX,CH,CA,SF,GA,KQ,OP7+,KM,EP','hdml' => '','wml' => '');
	/**
	 *
	 *  $_browser_quirks
	 *      desc    : 2D Array of browser quirks present in which browser
	 *              : in key => value pairs.
	 *              : key   = quirk
	 *              : value = search parameter for browsers that feature the
	 *              :         quirk listed in the key (comma delimited)
	 *              :         note: the search parameters rely on the values
	 *              :               set in the $_browsers array
	 *  @access public
	 *  @var string
	 */
	var $_browser_quirks = array('must_cache_forms' => 'NS,MZ,FB,PX,FX',
		'avoid_popup_windows' => 'IE3,LI,LX','cache_ssl_downloads' => 'IE',
		'break_disposition_header' => 'IE5.5','empty_file_input_value' => 'KQ',
		'scrollbar_in_way' => 'IE6');
	/**
	 *  @access private
	 *  @var array
	 */
	var $_browser_info = array('ua' => '','browser' => 'Unknown','version' => 0,
		'maj_ver' => 0,'min_ver' => 0,'letter_ver' => '','javascript' => '0.0',
		'platform' => 'Unknown','os' => 'Unknown','ip' => 'Unknown','cookies' =>
		'Unknown', // remains for backwards compatability
		'ss_cookies' => 'Unknown','st_cookies' => 'Unknown','language' => '',
		'long_name' => '','gecko' => '','gecko_ver' => '');
	/**
	 *  @access private
	 *  @var array
	 */
	var $_feature_set = array('html' => true,'images' => true,'frames' => true,
		'tables' => true,'java' => true,'plugins' => true,'iframes' => false,'css2' => false,
		'css1' => false,'xml' => false,'dom' => false,'wml' => false,'hdml' => false);
	/**
	 *  @access private
	 *  @var array
	 */
	var $_quirks = array('must_cache_forms' => false,'avoid_popup_windows' => false,
		'cache_ssl_downloads' => false,'break_disposition_header' => false,
		'empty_file_input_value' => false,'scrollbar_in_way' => false);
	/**
	 *  @access private
	 *  @var boolean
	 */
	var $_get_languages_ran_once = false;
	/**
	 *  @access private
	 *  @var string
	 */
	var $_browser_search_regex = '([a-z]+)([0-9]*)([0-9.]*)(up|dn|\+|\-)?';
	/**
	 *  @access private
	 *  @var string
	 */
	var $_language_search_regex = '([a-z-]{2,})';
	/**
	 *  @access private
	 *  @var string
	 */
	var $_browser_regex;
	/**
	 *  Performs some basic initialization and returns and object
	 *  @param string User Agent to parse
	 *  @param mixed array of settings
	 *          [check_cookies, default_language, allow_masqeurading]
	 *
	 *  @return object phpSniff object
	 */
	function phpSniff($UA = '',$settings = true) { //  populate the HTTP_USER_AGENT string
		//  20020425 :: rraymond
		//      routine for easier configuration of the client at runtime
		global $HTTP_SERVER_VARS;
		if(is_array($settings)) {
			$run = true;
			extract($settings);
		} else {
			// for backwards compatibility with 2.0.x series
			$run = (bool)$settings;
		}
		// if the user agent is empty, see if it exists somewhere
		if(empty($UA)) {
			if(isset($HTTP_SERVER_VARS['HTTP_USER_AGENT'])) {
				$UA = $HTTP_SERVER_VARS['HTTP_USER_AGENT'];
			} elseif(isset($_SERVER['HTTP_USER_AGENT'])) {
				$UA = $_SERVER['HTTP_USER_AGENT'];
			} else {
				// try to use the getenv function as a last resort
				$UA = getenv('HTTP_USER_AGENT');
			}
		}
		// if it's still empty, just return false as there is nothing to do
		if(empty($UA))
			return false;
		$this->_set_browser('ua',$UA);
		if($run)
			$this->init();
	}
	function init() {
		//  collect the ip
		$this->_get_ip();
		//  run the cookie check routine first
		//  [note: method only runs if allowed]
		$this->_test_cookies();
		//  rip the user agent to pieces
		$this->_get_browser_info();
		//    gecko build
		$this->_get_gecko();
		//  look for other languages
		$this->_get_languages();
		//  establish the operating platform
		$this->_get_os_info();
		//  determine javascript version
		$this->_get_javascript();
		//    determine current feature set
		$this->_get_features();
		//    point out any quirks
		$this->_get_quirks();
	}
	/**
	 *  turn the cookie check routine on or off
	 *  @param bool true or false    
	 */
	function check_cookies($yn) {
		$this->_check_cookies = (bool)$yn;
	}
	/**
	 *  allow browser masquerading
	 *  @param bool true or false    
	 */
	function allow_masquerading($yn) {
		$this->_allow_masquerading = (bool)$yn;
	}
	/**
	 *  set the default browser language
	 *  @param string valid language (ex: en-us)    
	 */
	function default_language($language) {
		$this->_default_language = $language;
	}
	/**
	 *  property
	 *  @param string property to return . optional (null returns entire array)
	 *  @return mixed array/string entire array or value of property
	 **/
	function property($p = null) {
		if($p == null) {
			return $this->_browser_info;
		} else {
			return $this->_browser_info[strtolower($p)];
		}
	}
	/**
	 *  get_property is an alias for property
	 *  @param string property to return . optional (null returns entire array)
	 *  @return mixed array/string entire array or value of property
	 **/
	function get_property($p) {
		return $this->property($p);
	}
	/**
	 *  is
	 *  @param string search phrase format = l:lang;b:browser
	 *  @return bool true on success
	 *  ex: $client->is('b:OP5Up');
	 **/
	function is($s) { // perform language search
		if(preg_match('/l:'.$this->_language_search_regex.'/i',$s,$match)) {
			if($match)
				return $this->_perform_language_search($match);
		}
		// perform browser search
		elseif(preg_match('/b:'.$this->_browser_search_regex.'/i',$s,$match)) {
			if($match)
				return $this->_perform_browser_search($match);
		}
		return false;
	}
	/**
	 *    browser_is
	 *    @param string search phrase for browser
	 *  @return bool true on success
	 *  ex: $client->browser_is('OP5Up');
	 **/
	function browser_is($s) {
		preg_match('/'.$this->_browser_search_regex.'/i',$s,$match);
		if($match)
			return $this->_perform_browser_search($match);
		return;
	}
	/**
	 *    language_is
	 *    @param string search phrase for language
	 *  @return bool true on success
	 *  ex: $client->language_is('en-US');
	 **/
	function language_is($s) {
		preg_match('/'.$this->_language_search_regex.'/i',$s,$match);
		if($match)
			return $this->_perform_language_search($match);
		return;
	}
	/**
	 *    checks to see if the browser supports any of the following features:
	 *  <ul>
	 *      <li>html
	 *      <li>images
	 *      <li>frames
	 *      <li>tables
	 *      <li>plugins
	 *      <li>iframes
	 *      <li>css2
	 *      <li>css1
	 *      <li>xml
	 *      <li>dom
	 *      <li>wml
	 *      <li>hdml
	 *  </ul>
	 *  <code>ex: $client->has_feature('html');</code>
	 *    @param string feature we're checking on
	 *  @return bool true on success
	 * 
	 **/
	function has_feature($s) {
		return $this->_feature_set[$s];
	}
	/**
	 *    checks to see if the browser has any of the following quirks:
	 *  <ul>
	 *      <li>must_cache_forms
	 *      <li>avoid_popup_windows
	 *      <li>cache_ssl_downloads
	 *      <li>break_disposition_header
	 *      <li>empty_file_input_value
	 *      <li>scrollbar_in_way
	 *  </ul>
	 *  <code>ex: $client->has_quirk('avoid_popup_windows');</code>
	 *    @param string quirk we're looking for
	 *  @return bool true on success
	 **/
	function has_quirk($s) {
		return $this->_quirks[$s];
	}
	/**
	 *  _perform_browser_search
	 *  @param string what we're searching for
	 *  @return bool true on success
	 *  @access private
	 **/
	function _perform_browser_search($data) {
		$search = array();
		$search['phrase'] = isset($data[0])?$data[0]:'';
		$search['name'] = isset($data[1])?strtolower($data[1]):'';
		$search['maj_ver'] = isset($data[2])?$data[2]:'';
		$search['min_ver'] = isset($data[3])?$data[3]:'';
		$search['direction'] = isset($data[4])?strtolower($data[4]):'';
		$looking_for = $search['maj_ver'].$search['min_ver'];
		if($search['name'] == 'aol' || $search['name'] == 'webtv') {
			return stristr($this->_browser_info['ua'],$search['name']);
		} elseif($this->_browser_info['browser'] == $search['name'] || $search['name'] ==
		'gecko') {
			if(strtolower($search['name']) == 'gecko') {
				$what_we_are = &$this->_browser_info['gecko_ver'];
			} else {
				$majv = $search['maj_ver']?$this->_browser_info['maj_ver']:'';
				$minv = $search['min_ver']?$this->_browser_info['min_ver']:'';
				$what_we_are = $majv.$minv;
			}
			if(($search['direction'] == 'up' || $search['direction'] == '+') && ($what_we_are >=
				$looking_for)) {
				return true;
			} elseif(($search['direction'] == 'dn' || $search['direction'] == '-') && ($what_we_are <=
			$looking_for)) {
				return true;
			} elseif($what_we_are == $looking_for) {
				return true;
			}
		}
		return false;
	}
	/**
	 *  @access private
	 */
	function _perform_language_search($data) { // if we've not grabbed the languages, then do so.
		$this->_get_languages();
		return stristr($this->_browser_info['language'],$data[1]);
	}
	/**
	 *  @access private
	 */
	function _get_languages() { // capture available languages and insert into container
		if(!$this->_get_languages_ran_once) {
			if($languages = getenv('HTTP_ACCEPT_LANGUAGE')) {
				$languages = preg_replace('/(;q=[0-9]+.[0-9]+)/i','',$languages);
			} else {
				$languages = $this->_default_language;
			}
			$this->_set_browser('language',$languages);
			$this->_get_languages_ran_once = true;
		}
	}
	/**
	 *  @access private
	 */
	function _get_os_info() { // regexes to use
		$regex_windows = '/([^dar]win[dows]*)[\s]?([0-9a-z]*)[\w\s]?([a-z0-9.]*)/i';
		$regex_mac = '/(68[k0]{1,3})|(ppc mac os x)|([p\S]{1,5}pc)|(darwin)/i';
		$regex_os2 = '/os\/2|ibm-webexplorer/i';
		$regex_sunos = '/(sun|i86)[os\s]*([0-9]*)/i';
		$regex_irix = '/(irix)[\s]*([0-9]*)/i';
		$regex_hpux = '/(hp-ux)[\s]*([0-9]*)/i';
		$regex_aix = '/aix([0-9]*)/i';
		$regex_dec = '/dec|osfl|alphaserver|ultrix|alphastation/i';
		$regex_vms = '/vax|openvms/i';
		$regex_sco = '/sco|unix_sv/i';
		$regex_linux = '/x11|inux/i';
		$regex_bsd = '/(free)?(bsd)/i';
		$regex_amiga = '/amiga[os]?/i';
		// look for Windows Box
		if(preg_match_all($regex_windows,$this->_browser_info['ua'],$match)) {
			/** Windows has some of the most ridiculous HTTP_USER_AGENT strings*/
			//$match[1][count($match[0])-1];
			$v = $match[2][count($match[0]) - 1];
			$v2 = $match[3][count($match[0]) - 1];
			// Establish NT 5.1 as Windows XP
			if(stristr($v,'NT') && $v2 == 5.1)
				$v = 'xp';
			// Establish NT 5.0 and Windows 2000 as win2k
			elseif($v == '2000')
				$v = '2k';
			elseif(stristr($v,'NT') && $v2 == 5.0)
				$v = '2k';
			// Establish 9x 4.90 as Windows 98
			elseif(stristr($v,'9x') && $v2 == 4.9)
				$v = '98';
			// See if we're running windows 3.1
			elseif($v.$v2 == '16bit')
				$v = '31';
			// otherwise display as is (31,95,98,NT,ME,XP)
			else
				$v .= $v2;
			// update browser info container array
			if(empty($v))
				$v = 'win';
			$this->_set_browser('os',strtolower($v));
			$this->_set_browser('platform','win');
		}
		//  look for amiga OS
		elseif(preg_match($regex_amiga,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','amiga');
			if(stristr($this->_browser_info['ua'],'morphos')) {
				// checking for MorphOS
				$this->_set_browser('os','morphos');
			} elseif(stristr($this->_browser_info['ua'],'mc680x0')) {
				// checking for MC680x0
				$this->_set_browser('os','mc680x0');
			} elseif(stristr($this->_browser_info['ua'],'ppc')) {
				// checking for PPC
				$this->_set_browser('os','ppc');
			} elseif(preg_match('/(AmigaOS [\.1-9]?)/i',$this->_browser_info['ua'],$match)) {
				// checking for AmigaOS version string
				$this->_set_browser('os',$match[1]);
			}
		}
		// look for OS2
		elseif(preg_match($regex_os2,$this->_browser_info['ua'])) {
			$this->_set_browser('os','os2');
			$this->_set_browser('platform','os2');
		}
		// look for mac
		// sets: platform = mac ; os = 68k or ppc
		elseif(preg_match($regex_mac,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','mac');
			$os = !empty($match[1])?'68k':'';
			$os = !empty($match[2])?'osx':$os;
			$os = !empty($match[3])?'ppc':$os;
			$os = !empty($match[4])?'osx':$os;
			$this->_set_browser('os',$os);
		}
		//  look for*nix boxes
		//  sunos sets: platform =*nix ; os = sun|sun4|sun5|suni86
		elseif(preg_match($regex_sunos,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			if(!stristr('sun',$match[1]))
				$match[1] = 'sun'.$match[1];
			$this->_set_browser('os',$match[1].$match[2]);
		}
		//  irix sets: platform =*nix ; os = irix|irix5|irix6|...
		elseif(preg_match($regex_irix,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os',$match[1].$match[2]);
		}
		//  hp-ux sets: platform =*nix ; os = hpux9|hpux10|...
		elseif(preg_match($regex_hpux,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$match[1] = str_replace('-','',$match[1]);
			$match[2] = (int)$match[2];
			$this->_set_browser('os',$match[1].$match[2]);
		}
		//  aix sets: platform =*nix ; os = aix|aix1|aix2|aix3|...
		elseif(preg_match($regex_aix,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','aix'.$match[1]);
		}
		//  dec sets: platform =*nix ; os = dec
		elseif(preg_match($regex_dec,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','dec');
		}
		//  vms sets: platform =*nix ; os = vms
		elseif(preg_match($regex_vms,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','vms');
		}
		//  sco sets: platform =*nix ; os = sco
		elseif(preg_match($regex_sco,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','sco');
		}
		//  unixware sets: platform =*nix ; os = unixware
		elseif(stristr($this->_browser_info['ua'],'unix_system_v')) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','unixware');
		}
		//  mpras sets: platform =*nix ; os = mpras
		elseif(stristr($this->_browser_info['ua'],'ncr')) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','mpras');
		}
		//  reliant sets: platform =*nix ; os = reliant
		elseif(stristr($this->_browser_info['ua'],'reliantunix')) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','reliant');
		}
		//  sinix sets: platform =*nix ; os = sinix
		elseif(stristr($this->_browser_info['ua'],'sinix')) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','sinix');
		}
		//  bsd sets: platform =*nix ; os = bsd|freebsd
		elseif(preg_match($regex_bsd,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os',$match[1].$match[2]);
		}
		//  last one to look for
		//  linux sets: platform =*nix ; os = linux
		elseif(preg_match($regex_linux,$this->_browser_info['ua'],$match)) {
			$this->_set_browser('platform','*nix');
			$this->_set_browser('os','linux');
		}
	}
	/**
	 *  @access private
	 */
	function _get_browser_info() {
		$this->_build_regex();
		if(preg_match_all($this->_browser_regex,$this->_browser_info['ua'],$results)) { // get the position of the last browser found
			$count = count($results[0]) - 1;
			// if we're allowing masquerading, revert to the next to last browser found
			// if possible, otherwise stay put
			if($this->_allow_masquerading && $count > 0)
				$count--;
			// insert findings into the container
			$this->_set_browser('browser',$this->_get_short_name($results[1][$count]));
			$this->_set_browser('long_name',$results[1][$count]);
			$this->_set_browser('maj_ver',$results[2][$count]);
			// parse the minor version string and look for alpha chars
			preg_match('/([.\0-9]+)?([\.a-z0-9]+)?/i',$results[3][$count],$match);
			if(isset($match[1])) {
				$this->_set_browser('min_ver',$match[1]);
			} else {
				$this->_set_browser('min_ver','.0');
			}
			if(isset($match[2]))
				$this->_set_browser('letter_ver',$match[2]);
			// insert findings into container
			$this->_set_browser('version',$this->_browser_info['maj_ver'].$this->property('min_ver'));
		}
	}
	/**
	 *  @access private
	 */
	function _get_ip() {
		if(getenv('HTTP_CLIENT_IP')) {
			$ip = getenv('HTTP_CLIENT_IP');
		} else {
			$ip = getenv('REMOTE_ADDR');
		}
		$this->_set_browser('ip',$ip);
	}
	/**
	 *  @access private
	 */
	function _build_regex() {
		$browsers = '';
		while(list($k,) = each($this->_browsers)) {
			if(!empty($browsers))
				$browsers .= "|";
			$browsers .= $k;
		}
		$version_string = "[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?";
		$this->_browser_regex = "/($browsers)$version_string/i";
	}
	/**
	 *  @access private
	 */
	function _get_short_name($long_name) {
		return $this->_browsers[strtolower($long_name)];
	}
	/**
	 *  @access private
	 */
	// medianes :: new test cookie routine
	function _test_cookies() {
		global $HTTP_COOKIE_VARS;
		$cookies = array();
		if(isset($_COOKIE)) {
			$cookies = $_COOKIE;
		} elseif(isset($HTTP_COOKIE_VARS)) {
			$cookies = $HTTP_COOKIE_VARS;
		}
		if($this->_check_cookies) {
			$fp = @fopen($this->_temp_file_path.$this->property('ip'),'r');
			if(!$fp) {
				$fp = @fopen($this->_temp_file_path.$this->property('ip'),'a');
				// make sure we have a valid file pointer
				if($fp) {
					fclose($fp);
					setcookie('phpSniff_session','ss',0,'/');
					setcookie('phpSniff_stored','st',time() + 3600 * 24 * 365,'/');
					$QS = getenv('QUERY_STRING');
					$script_path = getenv('PATH_INFO')?getenv('PATH_INFO'):getenv('SCRIPT_NAME');
					if(is_integer($pos = strpos(strrev($script_path),"php.xedni/")) && !$pos) {
						$script_path = strrev(substr(strrev($script_path),9));
					}
				}
				$location = 'http://'.getenv('SERVER_NAME').$script_path.($QS == ''?'':'?'.$QS);
				header("Location: $location");
				exit;
			} elseif($fp) {
				// we only want to proceed if we have a file pointer
				unlink($this->_temp_file_path.$this->property('ip'));
				fclose($fp);
				$this->_set_browser('ss_cookies',isset($cookies['phpSniff_session'])?'true':
					'false');
				$this->_set_browser('st_cookies',isset($cookies['phpSniff_stored'])?'true':
					'false');
				// delete the old cookies
				setcookie('phpSniff_session','',0,'/');
				setcookie('phpSniff_stored','',0,'/');
			}
		}
	}
	/**
	 *  @access private
	 */
	function _get_javascript() {
		$set = false;
		// see if we have any matches
		while(list($version,$browser) = each($this->_javascript_versions)) {
			$browser = explode(',',$browser);
			while(list(,$search) = each($browser)) {
				if($this->is('b:'.$search)) {
					$this->_set_browser('javascript',$version);
					$set = true;
					break;
				}
			}
			if($set)
				break;
		}
	}
	/**
	 *  @access private
	 */
	function _get_features() {
		while(list($feature,$browser) = each($this->_browser_features)) {
			$browser = explode(',',$browser);
			while(list(,$search) = each($browser)) {
				if($this->browser_is($search)) {
					$this->_set_feature($feature);
					break;
				}
			}
		}
	}
	/**
	 *  @access private
	 */
	function _get_quirks() {
		while(list($quirk,$browser) = each($this->_browser_quirks)) {
			$browser = explode(',',$browser);
			while(list(,$search) = each($browser)) {
				if($this->browser_is($search)) {
					$this->_set_quirk($quirk);
					break;
				}
			}
		}
	}
	/**
	 *  @access private
	 */
	function _get_gecko() {
		if(preg_match('/gecko\/([0-9]+)/i',$this->property('ua'),$match)) {
			$this->_set_browser('gecko',$match[1]);
			if(preg_match('/rv[: ]?([0-9a-z.+]+)/i',$this->property('ua'),$mozv)) {
				// mozilla release
				$this->_set_browser('gecko_ver',$mozv[1]);
			} elseif(preg_match('/(m[0-9]+)/i',$this->property('ua'),$mozv)) {
				// mozilla milestone version
				$this->_set_browser('gecko_ver',$mozv[1]);
			}
			// if this is a mozilla browser, get the rv: information
			if($this->browser_is($this->_get_short_name('mozilla'))) {
				if(preg_match('/([0-9]+)([\.0-9]+)([a-z0-9+]?)/i',$mozv[1],$match)) {
					$this->_set_browser('version',$mozv[1]);
					$this->_set_browser('maj_ver',$match[1]);
					$this->_set_browser('min_ver',$match[2]);
					$this->_set_browser('letter_ver',$match[3]);
				}
			}
		} elseif($this->is('b:'.$this->_get_short_name('mozilla'))) {
			// this is probably a netscape browser or compatible
			$this->_set_browser('long_name','netscape');
			$this->_set_browser('browser',$this->_get_short_name('netscape'));
		}
	}
	/**
	 *  @access private
	 */
	function _set_browser($k,$v) {
		$this->_browser_info[strtolower($k)] = strtolower($v);
	}
	/**
	 *  @access private
	 */
	function _set_feature($k) {
		$this->_feature_set[strtolower($k)] = !$this->_feature_set[strtolower($k)];
	}
	/**
	 *  @access private
	 */
	function _set_quirk($k) {
		$this->_quirks[strtolower($k)] = true;
	}

var $browserSearchOrder = array( // Most frequent standard web browsers are first in this list
	'icab','go!zilla','konqueror','links','lynx','omniweb','opera','msie 6\.0',
	'apachebench','wget', // Other standard web browsers
	'22acidownload','aol\\-iweng','amaya','amigavoyager','aweb','bpftp','chimera',
	'cyberdog','dillo','dreamcast','downloadagent','ecatch','emailsiphon',
	'encompass','friendlyspider','fresco','galeon','getright','headdump','hotjava',
	'ibrowse','intergo','k-meleon','linemodebrowser','lotus-notes','macweb',
	'multizilla','ncsa_mosaic','netpositive','nutscrape','msfrontpageexpress',
	'phoenix','firebird','firefox','safari','tzgeturl','viking','webfetcher',
	'webexplorer','webmirror','webvcr', // Site grabbers
	'teleport','webcapture','webcopier', // Music only browsers
	'real','winamp', // Works for winampmpeg and winamp3httprdr
	'windows-media-player','audion','freeamp','itunes','jetaudio','mint_audio',
	'mpg123','nsplayer','sonique','uplayer','xmms','xaudio',
	// PDA/Phonecell browsers
	'alcatel', // Alcatel
	'mot-', // Motorola
	'nokia', // Nokia
	'panasonic', // Panasonic
	'philips', // Philips
	'sonyericsson', // SonyEricsson
	'ericsson', // Ericsson (must be after sonyericsson
	'mmef','mspie','wapalizer','wapsilon','webcollage','up\.',
	// Works for UP.Browser and UP.Link
	// PDA/Phonecell I-Mode browsers
	'docomo','portalmmm', // Others (TV)
	'webtv', // Other kind of browsers
	'csscheck','w3m','w3c_css_validator','w3c_validator','wdg_validator','webzip',
	'staroffice','mozilla',
	// Must be at end because a lot of browsers contains mozilla in string
	'libwww' // Must be at end because some browser have both 'browser id' and 'libwww'
	);
// 05.08.07. boston, хак улучшения определения браузеров
var $browsersAlias = array('msie' => 'Microsoft Internet Explorer','netscape' =>
	'netscape', // Common web browsers text (IE and Netscape must not be in this list)
	'icab' => 'iCab','go!zilla' => 'Go!Zilla','konqueror' => 'Konqueror','links' =>
	'Links','lynx' => 'Lynx','omniweb' => 'OmniWeb','opera' => 'Opera','msie 6\.0' =>
	'Microsoft Internet Explorer 6.0','apachebench' => 'ApacheBench','wget' =>
	'Wget','22acidownload' => '22AciDownload','aol\\-iweng' => 'AOL-Iweng','amaya' =>
	'Amaya','amigavoyager' => 'AmigaVoyager','aweb' => 'AWeb','bpftp' => 'BPFTP',
	'chimera' => 'Chimera','cyberdog' => 'Cyberdog','dillo' => 'Dillo','dreamcast' =>
	'Dreamcast','downloadagent' => 'DownloadAgent','ecatch' => 'eCatch',
	'emailsiphon' => 'EmailSiphon','encompass' => 'Encompass','friendlyspider' =>
	'FriendlySpider','fresco' => 'ANT Fresco','galeon' => 'Galeon','getright' =>
	'GetRight','headdump' => 'HeadDump','hotjava' => 'Sun HotJava','ibrowse' =>
	'IBrowse','intergo' => 'InterGO','k-meleon' => 'K-Meleon','linemodebrowser' =>
	'W3C Line Mode Browser','lotus-notes' => 'Lotus Notes web client','macweb' =>
	'MacWeb','multizilla' => 'MultiZilla','ncsa_mosaic' => 'NCSA Mosaic',
	'netpositive' => 'NetPositive','nutscrape' => 'Nutscrape','msfrontpageexpress' =>
	'MS FrontPage Express','phoenix' => 'Phoenix','firebird' => 'Mozilla Firebird',
	'firefox' => 'Mozilla Firefox','safari' => 'Safari','tzgeturl' => 'TzGetURL',
	'viking' => 'Viking','webfetcher' => 'WebFetcher','webexplorer' =>
	'IBM-WebExplorer','webmirror' => 'WebMirror','webvcr' => 'WebVCR',
	// Site grabbers
	'teleport' => 'TelePort Pro','webcapture' => 'Acrobat','webcopier' =>
	'WebCopier', // Music only browsers
	'real' => 'RealAudio or compatible (media player)','winamp' =>
	'WinAmp (media player)', // Works for winampmpeg and winamp3httprdr
	'windows-media-player' => 'Windows Media Player (media player)','audion' =>
	'Audion (media player)','freeamp' => 'FreeAmp (media player)','itunes' =>
	'Apple iTunes (media player)','jetaudio' => 'JetAudio (media player)',
	'mint_audio' => 'Mint Audio (media player)','mpg123' => 'mpg123 (media player)',
	'nsplayer' => 'NetShow Player (media player)','sonique' =>
	'Sonique (media player)','uplayer' => 'Ultra Player (media player)','xmms' =>
	'XMMS (media player)','xaudio' =>
	'Some XAudio Engine based MPEG player (media player)', // PDA/Phonecell browsers
	'alcatel' => 'Alcatel Browser (PDA/Phone browser)','ericsson' =>
	'Ericsson Browser (PDA/Phone browser)','mot-' =>
	'Motorola Browser (PDA/Phone browser)','nokia' =>
	'Nokia Browser (PDA/Phone browser)','panasonic' =>
	'Panasonic Browser (PDA/Phone browser)','philips' =>
	'Philips Browser (PDA/Phone browser)','sonyericsson' =>
	'Sony/Ericsson Browser (PDA/Phone browser)','mmef' =>
	'Microsoft Mobile Explorer (PDA/Phone browser)','mspie' =>
	'MS Pocket Internet Explorer (PDA/Phone browser)','wapalizer' =>
	'WAPalizer (PDA/Phone browser)','wapsilon' => 'WAPsilon (PDA/Phone browser)',
	'webcollage' => 'WebCollage (PDA/Phone browser)','up\.' =>
	'UP.Browser (PDA/Phone browser)', // Works for UP.Browser and UP.Link
	// PDA/Phonecell I-Mode browsers
	'docomo' => 'I-Mode phone (PDA/Phone browser)','portalmmm' =>
	'I-Mode phone (PDA/Phone browser)', // Others (TV)
	'webtv' => 'WebTV browser', // Other kind of browsers
	'csscheck' => 'WDG CSS Validator','w3m' => 'w3m','w3c_css_validator' =>
	'W3C CSS Validator','w3c_validator' => 'W3C HTML Validator','wdg_validator' =>
	'WDG HTML Validator','webzip' => 'WebZIP','staroffice' => 'StarOffice',
	'mozilla' => 'Mozilla','libwww' => 'LibWWW',);


// BrowsersHashAreGrabber
// Put here an entry for each browser in BrowsersSearchIDOrder that are grabber
// browsers.
//---------------------------------------------------------------------------
var $BrowsersHereAreGrabbers = array('teleport' => '1','webcapture' => '1','webcopier' => '1',);


// BrowsersHashIcon
// Each Browsers Search ID is associated to a string that is the name of icon
// file for this browser.
//---------------------------------------------------------------------------
var $BrowsersHashIcon = array( // Standard web browsers
	'msie' => 'msie','netscape' => 'netscape','icab' => 'icab','go!zilla' =>
	'gozilla','konqueror' => 'konqueror','links' => 'notavailable','lynx' => 'lynx',
	'omniweb' => 'omniweb','opera' => 'opera','wget' => 'notavailable',
	'22acidownload' => 'notavailable','aol\\-iweng' => 'notavailable','amaya' =>
	'amaya','amigavoyager' => 'notavailable','aweb' => 'notavailable','bpftp' =>
	'notavailable','chimera' => 'chimera','cyberdog' => 'notavailable','dillo' =>
	'notavailable','dreamcast' => 'dreamcast','downloadagent' => 'notavailable',
	'ecatch' => 'notavailable','emailsiphon' => 'notavailable','encompass' =>
	'notavailable','friendlyspider' => 'notavailable','fresco' => 'notavailable',
	'galeon' => 'galeon','getright' => 'getright','headdump' => 'notavailable',
	'hotjava' => 'notavailable','ibrowse' => 'ibrowse','intergo' => 'notavailable',
	'k-meleon' => 'kmeleon','linemodebrowser' => 'notavailable','lotus-notes' =>
	'notavailable','macweb' => 'notavailable','multizilla' => 'multizilla',
	'ncsa_mosaic' => 'notavailable','netpositive' => 'netpositive','nutscrape' =>
	'notavailable','msfrontpageexpress' => 'notavailable','phoenix' => 'phoenix',
	'firebird' => 'firebird','safari' => 'safari','tzgeturl' => 'notavailable',
	'viking' => 'notavailable','webfetcher' => 'notavailable','webexplorer' =>
	'notavailable','webmirror' => 'notavailable','webvcr' => 'notavailable',
	// Site grabbers
	'teleport' => 'teleport','webcapture' => 'adobe','webcopier' => 'webcopier',
	// Music only browsers
	'real' => 'mediaplayer','winamp' => 'mediaplayer',
	// Works for winampmpeg and winamp3httprdr
	'windows-media-player' => 'mediaplayer','audion' => 'mediaplayer','freeamp' =>
	'mediaplayer','itunes' => 'mediaplayer','jetaudio' => 'mediaplayer',
	'mint_audio' => 'mediaplayer','mpg123' => 'mediaplayer','nsplayer' =>
	'mediaplayer','sonique' => 'mediaplayer','uplayer' => 'mediaplayer','xmms' =>
	'mediaplayer','xaudio' => 'mediaplayer', // PDA/Phonecell browsers
	'alcatel' => 'pdaphone', // Alcatel
	'ericsson' => 'pdaphone', // Ericsson
	'mot-' => 'pdaphone', // Motorola
	'nokia' => 'pdaphone', // Nokia
	'panasonic' => 'pdaphone', // Panasonic
	'philips' => 'pdaphone', // Philips
	'sonyericsson' => 'pdaphone', // Sony/Ericsson
	'mmef' => 'pdaphone','mspie' => 'pdaphone','wapalizer' => 'pdaphone','wapsilon' =>
	'pdaphone','webcollage' => 'pdaphone','up\.' => 'pdaphone',
	// Works for UP.Browser and UP.Link
	// PDA/Phonecell I-Mode browsers
'docomo' => 'pdaphone','portalmmm' => 'pdaphone', // Others (TV)
	'webtv' => 'webtv', // Other kind of browsers
	'csscheck' => 'notavailable','w3m' => 'notavailable','w3c_css_validator' =>
	'notavailable','w3c_validator' => 'notavailable','wdg_validator' =>
	'notavailable','webzip' => 'webzip','staroffice' => 'staroffice','mozilla' =>
	'mozilla','libwww' => 'notavailable');

/**
* AWSTATS BROWSERS DATABASE
* If you want to add a Browser to extend AWStats database detection capabilities,
* you must add an entry in BrowsersSearchIDOrder and in BrowsersHashIDLib.
*/

var $osSearchOrder = array('windows nt 6\.0','windows nt 5\.2','windows nt 5\.1',
	'windows nt 5\.0','winnt4\.0','winnt','windows 98','windows 95','win98','win95',
	'mac os x','debian','freebsd','linux','ppc','beos','sunos','apachebench','aix',
	'irix','osf','hp-ux','netbsd','bsdi','openbsd','gnu','unix');

var $osAlias = array('windows nt 6\.0' => 'Windows Longhorn','windows nt 5\.2' =>
	'Windows 2003','windows nt 5\.0' => 'Windows 2000','windows nt 5\.1' =>
	'Windows XP','winnt' => 'Windows NT','winnt 4\.0' => 'Windows NT','windows 98' =>
	'Windows 98','win98' => 'Windows 98','windows 95' => 'Windows 95','win95' =>
	'Windows 95','sunos' => 'Sun Solaris','freebsd' => 'FreeBSD','ppc' =>
	'Macintosh','mac os x' => 'Mac OS X','linux' => 'Linux','debian' => 'Debian',
	'beos' => 'BeOS','winnt4\.0' => 'Windows NT 4.0','apachebench' => 'ApacheBench',
	'aix' => 'AIX','irix' => 'Irix','osf' => 'DEC OSF','hp-ux' => 'HP-UX','netbsd' =>
	'NetBSD','bsdi' => 'BSDi','openbsd' => 'OpenBSD','gnu' => 'GNU/Linux','unix' =>
	'Unknown Unix system'
);
}